﻿// demon6-类和对象-3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

/*
用一个已存在的对象创建新的对象，不会调用（普通）构造函数，而是调用拷贝构造函数。
如果类中没有定义拷贝构造函数，编译器将提供一个拷贝构造函数，它的功能是把已存在对象的成员
变量赋值给新对象的成员变量。

用一个已存在的对象创建新的对象语法：
类名 新对象名(已存在的对象名);
类名 新对象名=已存在的对象名;

拷贝构造函数的语法：
类名(const 类名& 对象名){......}

注意：
 访问权限必须是 public。
 函数名必须与类名相同。
 没有返回值，不写 void。
 如果类中定义了拷贝构造函数，编译器将不提供默认的拷贝构造函数。
 以值传递的方式调用函数时，如果实参为对象，会调用拷贝构造函数。
 函数以值的方式返回对象时，可能会调用拷贝构造函数（VS 会调用，Linux 不会，g++编译器做了优化）。
 拷贝构造函数可以重载，可以有默认参数。
类名(......,const 类名& 对象名,......){......}
 如果类中重载了拷贝构造函数却没有定义默认的拷贝构造函数，编译器也会提供默认的拷贝构造函数。
*/

/*
#include <iostream>
using namespace std;
class DataTime {
public:

	DataTime(int year = 1, int month = 1, int day = 1)
	{
		cout << "调用一次构造函数DataTime()" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	DataTime(const DataTime& d1)                                   //拷贝构造函数,这里必须传引用，否则引起无穷递归
	{                                                              //加const防止d1指向的内容被修改
		_year = d1._year;
		_month = d1._month;
		_day = d1._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

//传值调用
void fun1(DataTime d) {               //d是d1的拷贝

}
//传引用
void fun2(DataTime&rd) {              //rd是d1的别名，没有拷贝

}

int main()
{
	DataTime d1(2024, 9, 14);
	//C++规定，自定义的类型都会调用拷贝构造
	fun1(d1);                                //调用fun1(d1)实际上先进入的拷贝构造函数DataTime(DataTime& d1)，继续调用才会进入fun1()函数里 
	fun2(d1);                                //这里不会调用拷贝构造

}
*/


/*
#include <iostream>
using namespace std;

class Time {
public:

	~Time()                                                         //析构函数
	{
		cout << "调用一次析构函数~Time()" << endl;
	}
	Time() = default;                                              //强制自动生成默认构造函数
	Time(const Time &t)                                            //拷贝构造函数也是构造函数，需要手动添加构造函数或上述强制生成默认构造函数
	{
		cout << "调用一次拷贝构造函数Time(Time &d)" << endl;
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
	}
private: 
	int _hour;
	int _minute;
	int _second;
};

class Data {
public:

	Data(int year=1,int month=1,int day=1)
	{
		cout << "调用一次构造函数Data()->"<<_year << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	Data(Data& d1)                                   //拷贝构造函数,这里必须传引用，否则引起无穷递归
	{
		this->_year = d1._year;
		this->_month = d1._month;
		this->_day = d1._day;
		cout << "this->" << this << endl;
	}
	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};


	int main()
		{
			Data d1(2024, 9, 14);
			Data d2(d1);                                 //拷贝构造函数
		}
*/


//浅拷贝，也是值拷贝，拷贝的是数值

/*
#include<iostream>
using namespace std;

class A {
public:

	A(int year=1,int month=1,int day=1) {                                             //构造
		_year = year;
		_month = month;
		_day = day;
	}

	A(const A& a1) {                                  //拷贝构造
		_year = a1._year;
		_month = a1._month;
		_day = a1._day;
		cout << "调用一次拷贝构造函数A(const A& a1)" << endl;
	}

	void Pint() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	~A() {                                            //析构
		cout << "调用~A()函数" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	A a1(2024,9,18);
	A a2(a1);
	a1.Pint();
	a2.Pint();
	return 0;
}
*/


//栈调用的时候，浅拷贝造成空间进行两次释放，导致报错
/*
#include<iostream>
using namespace std;

typedef int DataType;
class Stack {                                                       //栈
public:
	Stack(size_t capacity=10) {                                     //构造函数，初始化栈;
		_array = (DataType*)malloc(sizeof(DataType)*capacity);      //扩容
		if ( nullptr == _array) {
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity =capacity;
	}

	void Push(const DataType & data) {                            //压栈
		_array[_size] = data;                                     //尾插
		_size++;                                                  //尺寸+1
	}

	~Stack() {
		if (_array) {
			free(_array);
			_array = nullptr;
			_size = 0;
			_capacity = 0;
		}
	}
private:
	DataType* _array;
	int _size;
	int _capacity;
};

int main()
{
	Stack st1;           //报错
	Stack st2(st1);      //默认生成一份拷贝构造函数是会出问题的，导致同一块空间释放两次
	                     //对象st1和对象st2的_array使用的是同一块空间，默认形成一份拷贝构造，是浅拷贝，使用同一块空间
}
*/

//修正方法，使用深拷贝，让对象st1和st2的_array使用不同的空间存放，一旦涉及指针就要有深拷贝

/*
#include<iostream>
using namespace std;

typedef int  DataType;
class Stack {                                                         //栈
public:
	Stack(size_t capacity = 10) {                                     //构造函数，初始化栈;
		_array = (DataType*)malloc(sizeof(DataType) * capacity);      //扩容
		if (nullptr == _array) {
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}

	Stack(const Stack& st1) {                                                   //拷贝构造函数，把对象st1拷贝给st2
		DataType* tmp = (DataType*)malloc(sizeof(DataType)*st1._capacity);      //开辟空间
		if (tmp == nullptr) {
			perror("malloc申请空间失败！");
			exit(-1);
		}
		memcpy(tmp, st1._array, sizeof(DataType) * st1._size);                 //把st1的内容给中间变量tmp
		_array = tmp;
		_size = st1._size;
		_capacity = st1._capacity;

	}

	void Push(const DataType& data) {                               //压栈
		_array[_size] = data;                                       //尾插
		_size++;                                                    //尺寸+1
	}

	~Stack() {
		if (_array) {
			free(_array);
			_array = nullptr;
			_size = 0;
			_capacity = 0;
		}
	}
private:
	DataType* _array=nullptr;
	size_t _size=0;
	size_t _capacity=0;
};

int main()
{
	Stack st1;           //
	Stack st2(st1);      //深拷贝，对象st1和对象st2使用不同的空间，
}
*/


//对比日期类的大小的简单操作
/*
#include<iostream>
using namespace std;

class DataTime {
public:
	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	DataTime(int year=1,int month =1,int day=1) {
		_year = year;
		_month = month;
		_day = day;
		cout << "调用一次构造函数DataTime(int year=1,int month =1,int day=1)" << endl;
	}

	DataTime(const DataTime& d1) {
		_year = d1._year;
		_month = d1._month;
		_day = d1._day;
		cout << "调用一次拷贝构造DataTime(const DataTime& d1)" << endl;
	}

	~DataTime() {
		cout << "调用一次析构函数~DataTime()" << endl;
	}
	

//private:                                                         //这里把成员对象公有了，不然类外面不能调用成员变量
	int _year=0;
	int _month=0;
	int _day=0;
};

bool DateEqual(const DataTime& x, const DataTime& y) {             //对比两个对象
	return x._year == y._year
		&& x._month == y._month
		&& x._day == y._day;
}
bool Dateless(const DataTime& x, const DataTime& y) {
	if (x._year < y._year)
	{
		return true;
	}
	else if (x._year == y._year)
	{
		if (x._month < y._month)
		{
			return true;
		}
		else if (x._month == y._month)
		{
			return x._day < y._day;
		}
	}
	return false;
}

int main() {

	DataTime d1(2024,9,18);
	DataTime d2(d1);
	d1.Print();
	d2.Print();
	cout << DateEqual(d1,d2) << endl;
	cout << Dateless(d1, d2) << endl;

}
*/

//改进方法
/*
#include<iostream>
using namespace std;

class DataTime {
public:
	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	DataTime(int year = 1, int month = 1, int day = 1) {
		_year = year;
		_month = month;
		_day = day;
		cout << "调用一次构造函数DataTime(int year=1,int month =1,int day=1)" << endl;
	}

	DataTime(const DataTime& d1) {
		_year = d1._year;
		_month = d1._month;
		_day = d1._day;
		cout << "调用一次拷贝构造DataTime(const DataTime& d1)" << endl;
	}

	~DataTime() {
		cout << "调用一次析构函数~DataTime()" << endl;
	}

	bool operator==(const DataTime& y) {             //对比两个对象，
		return this->_year == y._year                //因为有隐含的this指针,这里直接写成员变量即可
			&& _month == y._month
			&& _day == y._day;
	}
	bool operator<(const DataTime& y) {
		if (_year < y._year)
		{
			return true;
		}
		else if (_year == y._year)
		{
			if (_month < y._month)
			{
				return true;
			}
			else if (_month == y._month)
			{
				return _day < y._day;
			}
		}
		return false;
	}
private:                                                       
	int _year = 0;
	int _month = 0;
	int _day = 0;
};


int main() {

	DataTime d1(2024, 9, 18);
	DataTime d2(2024,9,19);
	d1.Print();
	d2.Print();
	cout << d1.operator==(d2) << endl;                //运算符重载，调用成员对象
	cout << d1.operator<(d2) << endl;
}
*/